// 原型模式
// 软件开发过程中，开发者们常遇到一个问题：我们需要创建许多类实例（类的基本属性相同，但却各有不同的特性）。
// 遇到这种情况，我们可以通过为每个对象创建一个子类来实现，但这样并不是一个好的办法。我们都知道对象复合是比创建子类更加灵活的一种选择。这时我们就可以选择使用原型模式来构建这个类。
// 原型模式：用原型实例指定创建对象的种类，并且通过拷贝这些原型创建新的对象。原型类提供一个克隆自身的接口。
//
// 假设，我们要创建3个颜色不同的盒子，每个盒子的形状大小全都一样。
//
#include <string>
#include <iostream>

// prototype
class Box {
public:
    Box() = default;
    virtual ~Box() = default;

    virtual Box *clone() = 0;
    virtual void init(const std::string& color) = 0;
};

// concretePrototype
class ConcreteBox: public Box {
public:
    ConcreteBox(std::string name) : m_name(name) {}

    ConcreteBox(const ConcreteBox& other) { m_name = other.m_name; }
    Box* clone() { return new ConcreteBox(*this); }

    virtual void init(const std::string& color) { m_color = color; }
    void show() const { std::cout << m_name << ":" << m_color << std::endl; }
private:
    std::string m_name;
    std::string m_color;
};

int main(int argc, const char **argv) {
    ConcreteBox* pBox = new ConcreteBox("superBox");
    pBox->init("red");

    ConcreteBox* pConBox =  dynamic_cast<ConcreteBox*>(pBox->clone());
    if (pConBox == nullptr) return -1;

    pConBox->init("blue");

    pBox->show();
    pConBox->show();
    return 0;
}
